package com.hskn.hss.module.carTrack.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hskn.hss.core.utils.LoginUtils;
import com.hskn.hss.core.utils.uuid.IdUtils;
import com.hskn.hss.entity.AjaxResult;
import com.hskn.hss.exception.HssException;
import com.hskn.hss.module.alarmcar.entity.AlarmCar;
import com.hskn.hss.module.alarmcar.mapper.AlarmCarMapper;
import com.hskn.hss.module.carTrack.dto.CarTrackDto;
import com.hskn.hss.module.carTrack.entity.CarTrack;
import com.hskn.hss.module.carTrack.mapper.CarTrackMapper;
import com.hskn.hss.module.carTrack.service.CarTrackService;
import com.hskn.hss.module.carTrack.to.AlarmAndViolationCarTo;
import com.hskn.hss.module.carTrack.to.CleanListTo;
import com.hskn.hss.module.carTrack.to.MileageAndOilWearTo;
import com.hskn.hss.module.carTrack.vo.*;
import com.hskn.hss.module.carTrackOriginal.to.CarTrackGridTo;
import com.hskn.hss.module.carTrackOriginal.to.FacilitiesVo;
import com.hskn.hss.module.carviolation.entity.CarViolation;
import com.hskn.hss.module.carviolation.mapper.CarViolationMapper;
import com.hskn.hss.module.common.to.OilNumTO;
import com.hskn.hss.module.grid.entity.Grid;
import com.hskn.hss.module.grid.mapper.GridMapper;
import com.hskn.hss.module.gridSnapshot.entity.GridSnapshot;
import com.hskn.hss.module.gridSnapshot.mapper.GridSnapshotMapper;
import com.hskn.hss.module.jobset.entity.Jobset;
import com.hskn.hss.module.kfkcarlocation.entity.KfkCarLocation;
import com.hskn.hss.module.kfkcarlocation.service.IKfkCarLocationService;
import com.hskn.hss.module.oilDevice.domain.StateOilDevice;
import com.hskn.hss.module.oilDevice.mapper.StateOilDeviceMapper;
import com.hskn.hss.module.rptCarWork.entity.RptCarWork;
import com.hskn.hss.module.rptCarWork.mapper.RptCarWorkMapper;
import com.hskn.hss.module.rptCarWorkFacility.entity.RptCarWorkFacility;
import com.hskn.hss.module.rptCarWorkFacility.mapper.RptCarWorkFacilityMapper;
import com.hskn.hss.module.tlcar.entity.TlCar;
import com.hskn.hss.module.tlcar.mapper.TlCarMapper;
import com.hskn.hss.module.tlcar.service.ITlCarService;
import com.hskn.hss.module.tlfacilities.entity.TlFacilities;
import com.hskn.hss.module.tlfacilities.mapper.TlFacilitiesMapper;
import com.hskn.hss.module.tlfacilitietype.mapper.TlFacilitiesTypeMapper;
import com.hskn.hss.module.workgroup.mapper.WorkGroupMapper;
import com.hskn.hss.module.workkaoqin.mapper.WorkKaoqinMapper;
import com.hskn.hss.utils.*;
import com.hskn.hss.utils.redis.RedisUtil;
import com.hskn.hss.utils.redis.key.CarTrackLastOneKey;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hskn
 * @since 2021-05-21
 */
@Slf4j
@Service
public class CarTrackServiceImpl extends ServiceImpl<CarTrackMapper, CarTrack> implements CarTrackService {

    @Autowired
    LocationUtils locationUtil;
    @Resource
    private CarTrackMapper carTrackMapper;
    @Resource
    private GridMapper gridMapper;
    @Resource
    private TlFacilitiesMapper tlFacilitiesMapper;
    @Resource
    private TlFacilitiesTypeMapper tlFacilitiesTypeMapper;
    @Resource
    private TlCarMapper tlCarMapper;
    @Resource
    private WorkGroupMapper workGroupMapper;
    @Resource
    private AlarmCarMapper alarmCarMapper;
    @Resource
    private CarViolationMapper carViolationMapper;
    @Resource
    private RptCarWorkMapper rptCarWorkMapper;
    @Resource
    private StateOilDeviceMapper stateOilDeviceMapper;
    @Resource
    private WorkKaoqinMapper workKaoqinMapper;
    @Resource
    private GridSnapshotMapper gridSnapshotMapper;
    @Resource
    private ITlCarService carService;
    @Resource
    private IKfkCarLocationService kfkCarLocationService;
    @Resource
    private RptCarWorkFacilityMapper rptCarWorkFacilityMapper;


    /**
     * 根据时间排序（其他排序如根据id排序也类似）
     *
     * @param orderByAlarmAndViolationCars
     */
    private static void ListSort(List<OrderByAlarmAndViolationCar> orderByAlarmAndViolationCars) {
        //用Collections这个工具类传list进来排序
        Collections.sort(orderByAlarmAndViolationCars, new Comparator<OrderByAlarmAndViolationCar>() {
            @Override
            public int compare(OrderByAlarmAndViolationCar o1, OrderByAlarmAndViolationCar o2) {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date dt1 = null;
                Date dt2 = null;
                try {
                    dt1 = format.parse(StringUtils.DateFormat(o1.getTime()));
                    dt2 = format.parse(StringUtils.DateFormat(o2.getTime()));

                } catch (Exception e) {
                    e.printStackTrace();
                }
                return dt2.compareTo(dt1);
            }
        });
    }

    @Override
    public List mList(JSONObject params) throws HssException {

        String uid = LoginUtils.getUser().getUid();
        JSONObject json = new JSONObject();
        //车辆轨迹queryWrapper
        QueryWrapper<CarTrack> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        String carId = params.getString("carId");
        if (StringUtils.isNotEmpty(carId)) {
            //车辆轨迹queryWrapper
            queryWrapper.lambda().eq(CarTrack::getCarId, carId);
        }
        String starttime = params.getString("starttime");
        String endtime = params.getString("endtime");
        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            //车辆轨迹queryWrapper
            queryWrapper.lambda().between(CarTrack::getTimestamp, starttime, endtime);
        }
        //车辆轨迹queryWrapper
        List<CarTrack> carTrackList = carTrackMapper.selectList(queryWrapper);

        return carTrackList;
    }

    @Override
    public AlarmAndViolationCar alarmAndViolationCarList(AlarmAndViolationCarTo alarmAndViolationCarTo) throws HssException {
        //轨迹表
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        //报警表
        QueryWrapper<AlarmCar> alarmCarQueryWrapper = new QueryWrapper<>();
        alarmCarQueryWrapper.lambda().orderByAsc(AlarmCar::getAlarmTime);
        //违规表
        QueryWrapper<CarViolation> carViolationQueryWrapper = new QueryWrapper<>();

        QueryWrapper<RptCarWork> rptCarWorkQueryWrapper = new QueryWrapper<>();

        String carId = alarmAndViolationCarTo.getCarId();
        Integer simplify = alarmAndViolationCarTo.getSimplify();
        if (StringUtils.isNotEmpty(carId)) {
            alarmCarQueryWrapper.lambda().eq(AlarmCar::getCarId, carId);
            carTrackQueryWrapper.lambda().eq(CarTrack::getCarId, carId);
            carViolationQueryWrapper.lambda().eq(CarViolation::getCarId, carId);
            rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getCarId, carId);
        }
        String starttime = alarmAndViolationCarTo.getStarttime();
        String endtime = alarmAndViolationCarTo.getEndtime();

        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            rptCarWorkQueryWrapper.lambda().between(RptCarWork::getWorkDate, starttime.substring(0, 10), endtime.substring(0, 10));
            carViolationQueryWrapper.lambda().between(CarViolation::getTime, starttime, endtime);
            alarmCarQueryWrapper.lambda().between(AlarmCar::getAlarmTime, starttime, endtime);
            carTrackQueryWrapper.lambda().between(CarTrack::getTimestamp, starttime, endtime);
        }
        rptCarWorkQueryWrapper.lambda().orderByAsc(RptCarWork::getPlanStartTime);
        List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(rptCarWorkQueryWrapper);
        Map<String, List<RptCarWork>> rptCarWorkMap = rptCarWorkList.stream().collect(Collectors.groupingBy(RptCarWork::getWorkDate));

        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
        List<Grid> gridList = gridMapper.selectList(new QueryWrapper<>());
        Map<String, Grid> gridMap = gridList.stream().collect(Collectors.groupingBy(Grid::getGridId, Collectors.collectingAndThen(toList(), grids -> grids.get(0))));
        long carSTime10 = System.currentTimeMillis();
        for (CarTrack carTrack : carTrackList) {
            List<RptCarWork> rptCarWorkList1 = rptCarWorkMap.get(StringUtils.dateToStr(carTrack.getWorkDay(), "yyyy-MM-dd"));
            if (null != rptCarWorkList1) {
                for (RptCarWork rptCarWork : rptCarWorkList1) {
                    if (null != gridMap.get(rptCarWork.getGridId()) && null != carTrack.getStatus() && carTrack.getStatus() == 1 &&
                            (carTrack.getTimestamp().compareTo(rptCarWork.getPlanStartTime()) >= 0 && carTrack.getTimestamp().compareTo(rptCarWork.getPlanEndTime()) <= 0)
                            && DistanceUtils.insideGrid(Double.parseDouble(carTrack.getLng()), Double.parseDouble(carTrack.getLat()), gridMap.get(rptCarWork.getGridId()))) {
                        carTrack.setIsWorkIng(1);
                        break;
                    } else {
                        carTrack.setIsWorkIng(0);
                    }
                }
            }
        }
        long carSTime11 = System.currentTimeMillis();
        log.info("=====carLocationHandle10=执行时间(毫秒)：{}", carSTime11 - carSTime10);

        for (int i = 0; i < carTrackList.size(); i++) {
            carTrackList.get(i).setIndex(i);
            carTrackList.get(i).setIsDanger(0);
            carTrackList.get(i).setIsWarning(0);
            carTrackList.get(i).setWarningStay(0);
        }
        Map<String, CarTrack> carTrackMap = carTrackList.stream().collect(Collectors.groupingBy(CarTrack::getId, Collectors.collectingAndThen(toList(), carTracks -> carTracks.get(0))));

        AlarmAndViolationCar alarmAndViolationCar = new AlarmAndViolationCar();

        List<OrderByAlarmAndViolationCar> orderByAlarmAndViolationCars = new ArrayList<>();

        List<OrderByAlarmAndViolationCar> alarmCarCollectVo = new ArrayList<>();
        List<OrderByAlarmAndViolationCar> warningStayCollectVo = new ArrayList<>();
        List<OrderByAlarmAndViolationCar> otherWarningCollectVo = new ArrayList<>();
        List<OrderByAlarmAndViolationCar> carViolationCollectVo = new ArrayList<>();

        //报警
        List<AlarmCar> alarmCarList = alarmCarMapper.selectList(alarmCarQueryWrapper);

        alarmCarList.forEach(alarmCar -> {
            OrderByAlarmAndViolationCar orderByAlarmAndViolationCar = new OrderByAlarmAndViolationCar();
            orderByAlarmAndViolationCar.setId(alarmCar.getAlarmCarId());
            orderByAlarmAndViolationCar.setAddress(alarmCar.getAddress());
            orderByAlarmAndViolationCar.setStartTime(alarmCar.getAlarmStartTime());
            orderByAlarmAndViolationCar.setEndTime(alarmCar.getAlarmEndTime());
            orderByAlarmAndViolationCar.setCarNumber(alarmCar.getCarName());
            orderByAlarmAndViolationCar.setTime(alarmCar.getAlarmTime());
            orderByAlarmAndViolationCar.setContent(alarmCar.getContent());
            orderByAlarmAndViolationCar.setTypeName(alarmCar.getAlarmTypeName());
            orderByAlarmAndViolationCar.setLat(alarmCar.getLat());
            orderByAlarmAndViolationCar.setLng(alarmCar.getLng());
            orderByAlarmAndViolationCar.setMessageType(1);
            List<CarTrackVo> dangerList = new ArrayList<>();
            if (null != carTrackMap.get(alarmCar.getCarTrackStartId()) && null != carTrackMap.get(alarmCar.getCarTrackEndId())) {
                for (int k = carTrackMap.get(alarmCar.getCarTrackStartId()).getIndex(); k <= carTrackMap.get(alarmCar.getCarTrackEndId()).getIndex(); k++) {
                    CarTrackVo carTrackVo = new CarTrackVo();
                    carTrackVo.setId(carTrackList.get(k).getId());
                    carTrackVo.setAddress(carTrackList.get(k).getAddress());
                    carTrackVo.setMessage(carTrackList.get(k).getMessage());
                    carTrackVo.setLat(carTrackList.get(k).getLat());
                    carTrackVo.setLng(carTrackList.get(k).getLng());
                    carTrackVo.setMessageType(1);
                    dangerList.add(carTrackVo);
                }
            }
            alarmCar.setTime(alarmCar.getAlarmTime());
            alarmCar.setMessageType(1);
            alarmCar.setDangerList(dangerList);
            alarmCar.setId(alarmCar.getAlarmCarId());
            orderByAlarmAndViolationCar.setDangerList(dangerList);
            orderByAlarmAndViolationCars.add(orderByAlarmAndViolationCar);
            alarmCarCollectVo.add(orderByAlarmAndViolationCar);
        });
        //违规
        List<CarViolation> carViolationList = carViolationMapper.selectList(carViolationQueryWrapper);

        //停留的集和
        List<CarViolation> warningStayCollect = carViolationList.stream().filter(carViolation -> null != carViolation.getRuleTypeName() && carViolation.getRuleTypeName().equals("车辆停留")).collect(toList());
        warningStayCollect.forEach(carViolation -> {
            OrderByAlarmAndViolationCar orderByAlarmAndViolationCar = new OrderByAlarmAndViolationCar();
            orderByAlarmAndViolationCar.setId(carViolation.getCarViolationId());
            orderByAlarmAndViolationCar.setAddress(carViolation.getAddress());
            orderByAlarmAndViolationCar.setStartTime(carViolation.getViolationStartTime());
            orderByAlarmAndViolationCar.setEndTime(carViolation.getViolationEndTime());
            orderByAlarmAndViolationCar.setCarNumber(carViolation.getCarName());
            orderByAlarmAndViolationCar.setTime(carViolation.getTime());
            orderByAlarmAndViolationCar.setContent(carViolation.getContent());
            orderByAlarmAndViolationCar.setTypeName(carViolation.getRuleTypeName());
            orderByAlarmAndViolationCar.setMessageType(3);
            orderByAlarmAndViolationCar.setLat(carViolation.getLat());
            orderByAlarmAndViolationCar.setLng(carViolation.getLng());
            orderByAlarmAndViolationCars.add(orderByAlarmAndViolationCar);
            List<CarTrackVo> warningStayList = new ArrayList<>();
            if (null != carTrackMap.get(carViolation.getCarTrackStartId()) && null != carTrackMap.get(carViolation.getCarTrackEndId())) {
                for (int k = carTrackMap.get(carViolation.getCarTrackStartId()).getIndex(); k <= carTrackMap.get(carViolation.getCarTrackEndId()).getIndex(); k++) {
                    CarTrackVo carTrackVo = new CarTrackVo();
                    carTrackVo.setId(carTrackList.get(k).getId());
                    carTrackVo.setAddress(carTrackList.get(k).getAddress());
                    carTrackVo.setMessage(carTrackList.get(k).getMessage());
                    carTrackVo.setLat(carTrackList.get(k).getLat());
                    carTrackVo.setLng(carTrackList.get(k).getLng());
                    carTrackVo.setMessageType(3);
                    warningStayList.add(carTrackVo);
                }
            }
            carViolation.setMessageType(3);
            carViolation.setId(carViolation.getCarViolationId());
            carViolation.setWarningStayList(warningStayList);
            warningStayCollectVo.add(orderByAlarmAndViolationCar);
            carViolationCollectVo.add(orderByAlarmAndViolationCar);
        });

        List<CarViolation> otherWarningCollect = carViolationList.stream().filter(carViolation -> null != carViolation.getRuleTypeName() && !carViolation.getRuleTypeName().equals("车辆停留")).collect(toList());
        otherWarningCollect.forEach(carViolation -> {
            OrderByAlarmAndViolationCar orderByAlarmAndViolationCar = new OrderByAlarmAndViolationCar();
            orderByAlarmAndViolationCar.setId(carViolation.getCarViolationId());
            orderByAlarmAndViolationCar.setAddress(carViolation.getAddress());
            orderByAlarmAndViolationCar.setStartTime(carViolation.getViolationStartTime());
            orderByAlarmAndViolationCar.setEndTime(carViolation.getViolationEndTime());
            orderByAlarmAndViolationCar.setCarNumber(carViolation.getCarName());
            orderByAlarmAndViolationCar.setTime(carViolation.getTime());
            orderByAlarmAndViolationCar.setContent(carViolation.getContent());
            orderByAlarmAndViolationCar.setTypeName(carViolation.getRuleTypeName());
            orderByAlarmAndViolationCar.setMessageType(2);
            orderByAlarmAndViolationCar.setLat(carViolation.getLat());
            orderByAlarmAndViolationCar.setLng(carViolation.getLng());
            List<CarTrackVo> otherWarningList = new ArrayList<>();
            if (null != carTrackMap.get(carViolation.getCarTrackStartId()) && null != carTrackMap.get(carViolation.getCarTrackEndId())) {
                for (int k = carTrackMap.get(carViolation.getCarTrackStartId()).getIndex(); k <= carTrackMap.get(carViolation.getCarTrackEndId()).getIndex(); k++) {
                    CarTrackVo carTrackVo = new CarTrackVo();
                    carTrackVo.setId(carTrackList.get(k).getId());
                    carTrackVo.setAddress(carTrackList.get(k).getAddress());
                    carTrackVo.setMessage(carTrackList.get(k).getMessage());
                    carTrackVo.setLat(carTrackList.get(k).getLat());
                    carTrackVo.setLng(carTrackList.get(k).getLng());
                    carTrackVo.setMessageType(2);
                    otherWarningList.add(carTrackVo);
                }
            }
            carViolation.setMessageType(2);
            carViolation.setId(carViolation.getCarViolationId());
            carViolation.setOtherWarningList(otherWarningList);
            orderByAlarmAndViolationCar.setOtherWarningList(otherWarningList);
            orderByAlarmAndViolationCars.add(orderByAlarmAndViolationCar);
            otherWarningCollectVo.add(orderByAlarmAndViolationCar);
            carViolationCollectVo.add(orderByAlarmAndViolationCar);
        });
        //车辆轨迹存入VO
        List<CarTrackCleanVo> carTrackCleanVoList = new ArrayList<>();
        for (CarTrack carTrack : carTrackList) {
            CarTrackCleanVo carTrackCleanVo = new CarTrackCleanVo();
            BeanUtils.copyProperties(carTrack, carTrackCleanVo);
            carTrackCleanVoList.add(carTrackCleanVo);
        }

        ListSort(orderByAlarmAndViolationCars);
        alarmAndViolationCar.setOrderByAlarmAndViolationCars(orderByAlarmAndViolationCars); //合并
        ListSort(alarmCarCollectVo);
        alarmAndViolationCar.setAlarmCarList(alarmCarCollectVo);
        ListSort(warningStayCollectVo);
        alarmAndViolationCar.setWarningStayCollect(warningStayCollectVo);
        ListSort(otherWarningCollectVo);
        alarmAndViolationCar.setOtherWarningCollect(otherWarningCollectVo);
        alarmAndViolationCar.setCarTrackList(carTrackCleanVoList);
        ListSort(carViolationCollectVo);
        alarmAndViolationCar.setCarViolationList(carViolationCollectVo);
        //简化点位
        if (simplify != null && simplify == 1) {
            cleanRepeat(alarmAndViolationCar);
            doSimplify(alarmAndViolationCar);
        }

        //更新设施ID
        QueryWrapper<RptCarWorkFacility> rptCarWorkFacilityQueryWrapper = new QueryWrapper<>();
        rptCarWorkFacilityQueryWrapper.lambda().between(RptCarWorkFacility::getWorkDate, alarmAndViolationCarTo.getStarttime().substring(0, 10), alarmAndViolationCarTo.getEndtime().substring(0, 10));
        rptCarWorkFacilityQueryWrapper.lambda().eq(RptCarWorkFacility::getCarId,alarmAndViolationCarTo.getCarId());
        List<RptCarWorkFacility> rptCarWorkFacilityList = rptCarWorkFacilityMapper.selectList(rptCarWorkFacilityQueryWrapper);
        List<RptCarWorkFacility> rptCarWorkFacilities = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(rptCarWorkFacilityList) && CollectionUtils.isNotEmpty(rptCarWorkList)){
            Map<String, List<RptCarWorkFacility>> rptCarWorkFacilityListMap = rptCarWorkFacilityList.stream().filter(rptCarWorkFacility -> null != rptCarWorkFacility.getRptCarWorkId()).collect(Collectors.groupingBy(RptCarWorkFacility::getRptCarWorkId));
            for (RptCarWork rptCarWork : rptCarWorkList) {
                List<RptCarWorkFacility> list = rptCarWorkFacilityListMap.get(rptCarWork.getId());
                rptCarWorkFacilities.addAll(list);
            }
        }
        Map<String,List<RptCarWorkFacility>> carTrackMaps = rptCarWorkFacilities.stream().filter(item-> null != item.getCarTrackId()).collect(Collectors.groupingBy(RptCarWorkFacility::getCarTrackId));
        for (CarTrackCleanVo carTrackCleanVo : carTrackCleanVoList) {
            List<RptCarWorkFacility> workFacilities = carTrackMaps.get(carTrackCleanVo.getId());
            if(CollectionUtils.isNotEmpty(workFacilities)){
                carTrackCleanVo.setFacilityId(String.join(",",workFacilities.stream().map(item->item.getCollectPointId()).collect(toList())));
            }
        }
        return alarmAndViolationCar;
    }

    //车辆轨迹去重
    private void cleanRepeat(AlarmAndViolationCar alarmAndViolationCar) {
        List<CarTrackCleanVo> newCarTrackList = new ArrayList<>();
        CarTrackCleanVo preCarTrack = null;
        for (CarTrackCleanVo carTrack : alarmAndViolationCar.getCarTrackList()) {
            if (preCarTrack == null) {
                preCarTrack = carTrack;
                newCarTrackList.add(carTrack);
            } else {
                if (DistanceUtils.measureDistance(Double.parseDouble(carTrack.getLng()), Double.parseDouble(carTrack.getLat()), Double.parseDouble(preCarTrack.getLng()), Double.parseDouble(preCarTrack.getLat())) < 10) {

                } else {
                    newCarTrackList.add(carTrack);
                }
            }
        }
        alarmAndViolationCar.setCarTrackList(newCarTrackList);
    }

    //车辆轨迹斜率计算
    private void doSimplify(AlarmAndViolationCar alarmAndViolationCar) {
        double lat1 = 0;
        double lat2 = 0;
        double lat3 = 0;
        double lng1 = 0;
        double lng2 = 0;
        double lng3 = 0;
        double k1 = 0;
        double k2 = 0;
        Integer index = 0;
        double a = 0;
        double s = 1;
        CarTrackCleanVo preCarTrack = null;
        List<CarTrackCleanVo> newCarTrackList = new ArrayList<>();
        for (CarTrackCleanVo carTrack : alarmAndViolationCar.getCarTrackList()) {
            index++;
            if (index == 1) {
                lat1 = Double.parseDouble(carTrack.getLat());
                lng1 = Double.parseDouble(carTrack.getLng());
                newCarTrackList.add(carTrack);
            } else if (index == 2) {
                lat2 = Double.parseDouble(carTrack.getLat());
                lng2 = Double.parseDouble(carTrack.getLng());
            } else {
                lat3 = Double.parseDouble(carTrack.getLat());
                lng3 = Double.parseDouble(carTrack.getLng());

                k1 = (lng1 == lng2) ? 99999999 : (lat1 - lat2) / (lng1 - lng2);
                k2 = (lng2 == lng3) ? 99999999 : (lat2 - lat3) / (lng2 - lng3);
                if ((k1 == 0 && k2 == 0) || (((k1 - k2) / k2) < s && ((k1 - k2) / k2) > s * -1)) {

                } else {
                    lat1 = lat2;
                    lng1 = lng2;
                    newCarTrackList.add(preCarTrack);
                }
                lat2 = lat3;
                lng2 = lng3;
            }
            preCarTrack = carTrack;
        }

        if (alarmAndViolationCar.getCarTrackList().size() >= 2) {
            newCarTrackList.add(preCarTrack);
        }
        alarmAndViolationCar.setCarTrackList(newCarTrackList);
    }

    @Override
    public List violationsAndAlarms(JSONObject params) throws HssException {

        List list = alarmCarMapper.violationsAndAlarms(params);
        return list;
    }

    @Override
    public JSONObject selectPage(JSONObject params) throws HssException {

        String uid = LoginUtils.getUser().getUid();
        JSONObject json = new JSONObject();
        QueryWrapper<CarTrack> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().orderByDesc(CarTrack::getTimestamp);
        String carId = params.getString("carId");
        if (StringUtils.isNotEmpty(carId)) {
            queryWrapper.lambda().eq(CarTrack::getCarId, carId);
        }
        String starttime = params.getString("starttime");
        String endtime = params.getString("endtime");
        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            queryWrapper.lambda().between(CarTrack::getTimestamp, starttime, endtime);
        }
        Long page = StringUtils.isEmpty(params.getLong("page")) ? 1 : params.getLong("page");
        Long size = StringUtils.isEmpty(params.getLong("size")) ? 10 : params.getLong("size");
        Page<CarTrack> carTrackPage = new Page<>(page, size, true);
        IPage<CarTrack> iPage = carTrackMapper.selectPage(carTrackPage, queryWrapper);
        json.put("total", iPage.getTotal());
        json.put("size", iPage.getSize());
        json.put("pages", iPage.getPages());
        json.put("current", iPage.getCurrent());
        json.put("list", iPage.getRecords());
        return json;
    }

    @Override
    public AjaxResult insert(JSONObject params) {
        CarTrack carTrack = params.getObject("data", CarTrack.class);
        int i = carTrackMapper.insert(carTrack);
        boolean flag = i > 0;
        if (flag) {
            return AjaxResult.success("操作成功");
        } else {
            return AjaxResult.fail("操作失败，请稍后再试");
        }
    }

    @Override
    public List<Grid> getCarTrackGrid(CarTrackGridTo carTrackGridTo) {

        QueryWrapper<RptCarWork> rptCarWorkQueryWrapper = new QueryWrapper<>();

        QueryWrapper<RptCarWorkFacility> rptCarWorkFacilityQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(carTrackGridTo.getCarId())) {
            rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getCarId, carTrackGridTo.getCarId());
            rptCarWorkFacilityQueryWrapper.lambda().eq(RptCarWorkFacility::getCarId, carTrackGridTo.getCarId());
        }
        if (StringUtils.isNotEmpty(carTrackGridTo.getStartDate()) && StringUtils.isNotEmpty(carTrackGridTo.getEndDate())) {
            rptCarWorkQueryWrapper.lambda().between(RptCarWork::getWorkDate, carTrackGridTo.getStartDate(), carTrackGridTo.getEndDate());
            rptCarWorkFacilityQueryWrapper.lambda().between(RptCarWorkFacility::getWorkDate, carTrackGridTo.getStartDate(), carTrackGridTo.getEndDate());
        }
        List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(rptCarWorkQueryWrapper);

        List<RptCarWorkFacility> rptCarWorkFacilityList = rptCarWorkFacilityMapper.selectList(rptCarWorkFacilityQueryWrapper);

        Map<String, Integer> map = new HashMap<>();
        for (RptCarWorkFacility carWorkFacility : rptCarWorkFacilityList) {
            map.put(carWorkFacility.getCollectPointId(), carWorkFacility.getCleanType());
        }

        List<String> gridsList = new ArrayList<>();
        QueryWrapper<TlFacilities> tlFacilitiesQueryWrapper = new QueryWrapper<>();
        List<TlFacilities> tlFacilitiesList = tlFacilitiesMapper.selectList(tlFacilitiesQueryWrapper);
        Map<String, TlFacilities> tlFacilitiesMap = tlFacilitiesList.stream().collect(Collectors.groupingBy(TlFacilities::getId, Collectors.collectingAndThen(toList(), values -> values.get(0))));

        List<FacilitiesVo> facilitiesVoList = new ArrayList<>();
        for (RptCarWork rptCarWork : rptCarWorkList) {
            gridsList.add(rptCarWork.getGridId());
            if (StringUtils.isNotEmpty(rptCarWork.getSjdIds())) {
                String[] split = rptCarWork.getSjdIds().split(",");
                for (String id : split) {
                    TlFacilities tlFacilities = tlFacilitiesMap.get(id);
                    if (null != tlFacilities) {
                        String[] faclAddr = tlFacilities.getFacladdr().split(",");
                        String lng = faclAddr[0];
                        String lat = faclAddr[1];
                        FacilitiesVo facilitiesVo = new FacilitiesVo();
                        Integer cleanType = map.get(tlFacilities.getId());
                        facilitiesVo.setIsClean(0);
                        if (null != cleanType) {
                            facilitiesVo.setIsClean(1);
                        }
                        facilitiesVo.setLng(lng);
                        facilitiesVo.setLat(lat);
                        facilitiesVo.setFacladdrdetail(tlFacilities.getFacladdrdetail());
                        facilitiesVo.setFaclname(tlFacilities.getFaclname());
                        facilitiesVo.setId(tlFacilities.getId());
                        facilitiesVoList.add(facilitiesVo);
                    }
                }
            }
        }
        //网格列表
        List<Grid> GridList = new ArrayList<>();
        if (!gridsList.isEmpty()) {
            QueryWrapper<Grid> gridQueryWrapper = new QueryWrapper<>();
            gridQueryWrapper.lambda().in(Grid::getGridId, gridsList);
            GridList = gridMapper.selectList(gridQueryWrapper);
            for (Grid grid : GridList) {
                grid.setFacilitiesVoList(facilitiesVoList);
            }
        }
        return GridList;
    }

    @Override
    public List getLiveLjqyCar(JSONObject params) throws HssException {

        String uid = LoginUtils.getUser().getUid();
        QueryWrapper<CarTrack> queryWrapper = new QueryWrapper<>();
        String timestamp = params.getString("timestamp");
        if (StringUtils.isNotEmpty(timestamp)) {
            queryWrapper.lambda().eq(CarTrack::getTimestamp, timestamp);
        }
        List<CarTrack> carTrackList = carTrackMapper.selectList(queryWrapper);
//        for (CarTrack carTrack : carTrackList) {
//            QueryWrapper<TlCar> tlCarQueryWrapper = new QueryWrapper<>();
//            tlCarQueryWrapper.lambda().eq(TlCar::getId, carTrack.getCarId());
//            //根据id查询车辆
//            List<TlCar> tlCarList = tlCarMapper.selectList(tlCarQueryWrapper);
//            for (TlCar tlCar : tlCarList) {
//                carTrack.setCarnumber(tlCar.getCarnumber());
//            }
//            //根据作业计划排班id 查询 垃圾清运
//            QueryWrapper<LjqyWorkPlan> ljqyWorkPlanQueryWrapper = new QueryWrapper<>();
//            ljqyWorkPlanQueryWrapper.lambda().in(LjqyWorkPlan::getLjqyWorkPlanId, carTrack.getShiftId());
//            List<LjqyWorkPlan> ljqyWorkPlanList = ljqyWorkPlanMapper.selectList(ljqyWorkPlanQueryWrapper);
//            for (LjqyWorkPlan ljqyWorkPlan : ljqyWorkPlanList) {
//                //根据班组id 查询 班组
//                QueryWrapper<WorkGroup> workGroupQueryWrapper = new QueryWrapper<>();
//                workGroupQueryWrapper.lambda().in(WorkGroup::getWorkGroupId, ljqyWorkPlan.getWorkGroupId());
//                List<WorkGroup> workGroupList = workGroupMapper.selectList(workGroupQueryWrapper);
//                for (WorkGroup workGroup : workGroupList) {
//                    carTrack.setGroupName(workGroup.getName());
//                }
//            }
//        }
        return carTrackList;
    }

    @Override
    public CleanPointVo cleanPoint() {
        Integer countSize = 0;

//        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
//        carTrackQueryWrapper.lambda().groupBy(CarTrack::getFacilityId);
//        carTrackQueryWrapper.lambda().eq(CarTrack::getJobType, 3);
//        carTrackQueryWrapper.lambda().eq(CarTrack::getCleanType, 0);
//        carTrackQueryWrapper.lambda().eq(CarTrack::getWorkDay, DateUtil.format(new Date(), "yyyy-MM-dd"));
//        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
//        Map<String, List<CarTrack>> carTrackStreamList = carTrackList.stream().collect(Collectors.groupingBy(CarTrack::getCarId));
        QueryWrapper<RptCarWorkFacility> rptCarWorkFacilityQueryWrapper = new QueryWrapper<>();
        rptCarWorkFacilityQueryWrapper.lambda().eq(RptCarWorkFacility::getWorkDate, DateUtil.format(new Date(), "yyyy-MM-dd"));
        List<RptCarWorkFacility> rptCarWorkFacilityList = rptCarWorkFacilityMapper.selectList(rptCarWorkFacilityQueryWrapper);
        Map<String, List<RptCarWorkFacility>> rptCarWorkFacilityListMap = rptCarWorkFacilityList.stream().filter(rptCarWorkFacility -> null != rptCarWorkFacility.getRptCarWorkId()).collect(Collectors.groupingBy(RptCarWorkFacility::getRptCarWorkId));

        QueryWrapper<RptCarWork> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByDesc(RptCarWork::getCreateTime);
        queryWrapper.lambda().eq(RptCarWork::getWorkDate, DateUtil.format(new Date(), "yyyy-MM-dd"));
        queryWrapper.lambda().eq(RptCarWork::getWorkType, 3);
        List<RptCarWork> list = rptCarWorkMapper.selectList(queryWrapper);
        CleanPointVo cleanPointVo = new CleanPointVo();
        Map<String, TlFacilities> tlFacilitiesMap = tlFacilitiesMapper.selectList(new QueryWrapper<>()).stream().collect(Collectors.groupingBy(TlFacilities::getId, Collectors.collectingAndThen(toList(), facilities -> facilities.get(0))));

        List<String> countCleanList = new ArrayList<>();
        List<String> cleanList = new ArrayList<>();
        Set<String> tlFacilitiesIdList = new HashSet<>();
        Set cleanFaclIds = new HashSet();
        for (RptCarWork rptCarWork : list) {
            if (StringUtils.isNotEmpty(rptCarWork.getSjdIds())) {
                String[] sjdIds = rptCarWork.getSjdIds().split(",");
                for (String sjdId : sjdIds) {
                    countCleanList.add(sjdId);
                    TlFacilities tlFacilities = tlFacilitiesMap.get(sjdId);
                    if (null != tlFacilities) {
                        tlFacilitiesIdList.add(tlFacilities.getId());
                    }
                }
                countSize += sjdIds.length;
                //根据 今天排班的 垃圾清运车的id 和 清理状态 获取 清理设施的数量
                List<RptCarWorkFacility> rptCarWorkFacilityList1 = rptCarWorkFacilityListMap.get(rptCarWork.getId());
                if (null != rptCarWorkFacilityList1) {
                    for (RptCarWorkFacility rptCarWorkFacility : rptCarWorkFacilityList1) {
                        String facilityId = rptCarWorkFacility.getCollectPointId();
                        Integer cleanType = rptCarWorkFacility.getCleanType();
                        if (null != cleanType && cleanType == 1) {
                            cleanFaclIds.add(facilityId);
                            cleanList.add(facilityId);
                        }
                    }
                }
            }
        }
        BigDecimal cleanRate = BigDecimal.ZERO;
        if (0 != countSize) {
            cleanRate = (new BigDecimal(cleanFaclIds.size()).divide(new BigDecimal(tlFacilitiesIdList.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))).setScale(0, BigDecimal.ROUND_UP);
        }

        List<String> reduce = countCleanList.stream().filter(item -> !cleanList.contains(item)).collect(toList());
        System.out.println("---差集 reduce1 (list1 - list2)---");
        reduce.parallelStream().forEach(System.out::println);
        Set<FacilitiesListVo> facilitiesListVoList = new HashSet<>();
        for (String id : reduce) {
            FacilitiesListVo facilitiesListVo = new FacilitiesListVo();
            TlFacilities tlFacilities = tlFacilitiesMap.get(id);
            if (null != tlFacilities) {
                facilitiesListVo.setId(tlFacilities.getId());
                facilitiesListVo.setName(tlFacilities.getFaclname());
                facilitiesListVo.setTypeName(tlFacilities.getFacltypename());
                facilitiesListVoList.add(facilitiesListVo);
            }
        }
        cleanPointVo.setFacilitiesListVoList(facilitiesListVoList);
        cleanPointVo.setCountSize(tlFacilitiesIdList.size());
        cleanPointVo.setCountClean(cleanFaclIds.size());
        cleanPointVo.setCountNotClean(facilitiesListVoList.size());
        cleanPointVo.setCleanRate(cleanRate);

        return cleanPointVo;
    }


    @Override
    public MileageAndOilWearVo mileageAndOilWear(MileageAndOilWearTo mileageAndOilWearTo) throws HssException {
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getCreateTime);
        String carId = mileageAndOilWearTo.getCarId();
        if (StringUtils.isNotEmpty(carId)) {
            carTrackQueryWrapper.lambda().eq(CarTrack::getCarId, carId);
        }
        String starttime = mileageAndOilWearTo.getStarttime();
        String endtime = mileageAndOilWearTo.getEndtime();
        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            carTrackQueryWrapper.lambda().between(CarTrack::getTimestamp, starttime, endtime);
        }
        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);

        QueryWrapper<RptCarWork> rptCarWorkQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(carId)) {
            rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getCarId, carId);
        }
        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            rptCarWorkQueryWrapper.lambda().between(RptCarWork::getWorkDate, starttime.substring(0, 10), endtime.substring(0, 10));
        }
        List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(rptCarWorkQueryWrapper);
        Map<String, List<RptCarWork>> rptCarWorkListMap = rptCarWorkList.stream().collect(Collectors.groupingBy(RptCarWork::getCarId));

        QueryWrapper<GridSnapshot> gridSnapshotQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            gridSnapshotQueryWrapper.lambda().between(GridSnapshot::getDate, starttime.substring(0, 10), endtime.substring(0, 10));
        }
        List<GridSnapshot> gridSnapshotList = gridSnapshotMapper.selectList(gridSnapshotQueryWrapper);


        Map<String, GridSnapshot> gridSnapshotMap = gridSnapshotList.stream().collect(Collectors.groupingBy(GridSnapshot::getGridId, Collectors.collectingAndThen(toList(), grids -> grids.get(0))));

        return getMileageAndOilWearVo(carTrackList, rptCarWorkListMap, gridSnapshotMap);
    }

    private MileageAndOilWearVo getMileageAndOilWearVo(List<CarTrack> carTrackList, Map<String, List<RptCarWork>> rptCarWorkListMap, Map<String, GridSnapshot> gridSnapshotMap) {
        MileageAndOilWearVo mileageAndOilWearVo = new MileageAndOilWearVo();
        //总里程数
        BigDecimal totalMileage = BigDecimal.ZERO;

        //加油量
        BigDecimal addOilWear = BigDecimal.ZERO;
        //在岗里程
        BigDecimal onGuardMileage = BigDecimal.ZERO;
        //空驶里程
        BigDecimal emptyMileage = BigDecimal.ZERO;
        //作业里程
        BigDecimal jobMileage = BigDecimal.ZERO;

        BigDecimal startOilMss = BigDecimal.ZERO;
        BigDecimal endOilMss = BigDecimal.ZERO;

        List<CarTrack> carTrackList2 = new ArrayList<>();
        for (int i = 0; i < carTrackList.size(); i++) {
            if (null != carTrackList.get(i).getOilMass() && 0 != carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO)) {
                carTrackList2.add(carTrackList.get(i));
            }
        }
        for (int i = 1; i < carTrackList.size(); i++) {
            Double distance = Double.parseDouble(String.valueOf(carTrackList.get(i).getDistanceBetween()));
            totalMileage = (MathUtils.getBigDecimal(distance).add(totalMileage));
        }

        for (int i = 1; i < carTrackList2.size(); i++) {
            Double addNumber = null == carTrackList2.get(i).getAddOilNum() ? 0D : carTrackList2.get(i).getAddOilNum();
            addOilWear = addOilWear.add(MathUtils.getBigDecimal(addNumber));
        }

        for (int i = 0; i < carTrackList.size(); i++) {
            if (null != carTrackList.get(i).getOilMass() && 0 != carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO)) {
                startOilMss = carTrackList.get(i).getOilMass();
                break;
            }
        }
        for (int i = carTrackList.size() - 1; i >= 0; i--) {
            if (null != carTrackList.get(i).getOilMass() && 0 != carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO)) {
                endOilMss = carTrackList.get(i).getOilMass();
                break;
            }
        }
        //油耗
        BigDecimal oilWear = MathUtils.getBigDecimal(startOilMss).subtract(MathUtils.getBigDecimal(endOilMss)).add(addOilWear).setScale(2, BigDecimal.ROUND_HALF_UP);

        Integer status = 0; // 0 表示空驶 1 表示作业
        for (int i = 0; i < carTrackList.size(); i++) {
            if (i != 0) {
                List<RptCarWork> rptCarWorkList = rptCarWorkListMap.get(carTrackList.get(i).getCarId());
                if (null != rptCarWorkList) {
                    for (RptCarWork rptCarWork : rptCarWorkList) {
                        if (null != gridSnapshotMap.get(rptCarWork.getGridId())) {
                            boolean insideCopyGrid = DistanceUtils.insideCopyGrid(Double.parseDouble(carTrackList.get(i).getLng()), Double.parseDouble(carTrackList.get(i).getLat()), gridSnapshotMap.get(rptCarWork.getGridId()));
                            if (insideCopyGrid) {
                                if (carTrackList.get(i).getTimestamp().compareTo(rptCarWork.getPlanStartTime()) >= 0 && carTrackList.get(i).getTimestamp().compareTo(rptCarWork.getPlanEndTime()) <= 0) {
                                    if (status.equals(0) || status.equals(1)) {
                                        onGuardMileage = (MathUtils.getBigDecimal(carTrackList.get(i).getDistanceBetween().doubleValue()).add(onGuardMileage));
                                    }
                                    if (status.equals(1)) {
                                        jobMileage = (MathUtils.getBigDecimal(locationUtil.getDistance(carTrackList.get(i - 1).getLat(), carTrackList.get(i - 1).getLng(), carTrackList.get(i).getLat(), carTrackList.get(i).getLng())).add(jobMileage));
                                    }
                                }
                            }
                        }
                    }
                }
            }
            status = carTrackList.get(i).getStatus();
        }
        mileageAndOilWearVo.setEmptyMileage((onGuardMileage.subtract(jobMileage)).divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP));
        mileageAndOilWearVo.setJobMileage(jobMileage.divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP));
        mileageAndOilWearVo.setOilWear(oilWear.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : oilWear);
        mileageAndOilWearVo.setTotalMileage(totalMileage.divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP));
        mileageAndOilWearVo.setOnGuardMileage(onGuardMileage.divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP));
        return mileageAndOilWearVo;
    }

    @Override
    public CarTrackDto lastCarTrack(CarTrackDto carTrackDto) throws HssException {

        CarTrack carTrack = RedisUtil.get(CarTrackLastOneKey.token, carTrackDto.getLastCarTrackTo().getCarId(), CarTrack.class);
        if (carTrack == null) {
            QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<CarTrack>();
            carTrackQueryWrapper.lambda().eq(CarTrack::getCarId, carTrackDto.getLastCarTrackTo().getCarId());
            carTrackQueryWrapper.lambda().orderByDesc(CarTrack::getTimestamp);
            carTrackQueryWrapper.lambda().last(" LIMIT 1");
            carTrack = carTrackMapper.selectOne(carTrackQueryWrapper);
        }
        carTrackDto.setCarTrack(carTrack);
        return carTrackDto;
    }

    public FaclCleanListVo cleanList(CleanListTo cleanListTo) throws HssException {
//        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
//        carTrackQueryWrapper.lambda().eq(CarTrack::getCarId, cleanListTo.getCarId());
//        carTrackQueryWrapper.lambda().between(CarTrack::getTimestamp, cleanListTo.getStarttime(), cleanListTo.getEndtime());
//        carTrackQueryWrapper.lambda().eq(CarTrack::getJobType, 3);
//        carTrackQueryWrapper.lambda().eq(CarTrack::getCleanType, 0);
//        carTrackQueryWrapper.lambda().groupBy(CarTrack::getFacilityId);
//        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
//        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
//        Map<String, List<CarTrack>> carTrackStreamList = carTrackList.stream().collect(Collectors.groupingBy(CarTrack::getCarId));

        QueryWrapper<RptCarWorkFacility> rptCarWorkFacilityQueryWrapper = new QueryWrapper<>();
        rptCarWorkFacilityQueryWrapper.lambda().between(RptCarWorkFacility::getWorkDate, cleanListTo.getStarttime().substring(0, 10), cleanListTo.getEndtime().substring(0, 10));
        List<RptCarWorkFacility> rptCarWorkFacilityList = rptCarWorkFacilityMapper.selectList(rptCarWorkFacilityQueryWrapper);
        Map<String, List<RptCarWorkFacility>> rptCarWorkFacilityListMap = rptCarWorkFacilityList.stream().filter(rptCarWorkFacility -> null != rptCarWorkFacility.getRptCarWorkId()).collect(Collectors.groupingBy(RptCarWorkFacility::getRptCarWorkId));


        QueryWrapper<RptCarWork> rptCarWorkQueryWrapper = new QueryWrapper<>();
        rptCarWorkQueryWrapper.lambda().orderByDesc(RptCarWork::getCreateTime);
        rptCarWorkQueryWrapper.lambda().between(RptCarWork::getWorkDate, cleanListTo.getStarttime().substring(0, 10), cleanListTo.getEndtime().substring(0, 10));
        rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getWorkType, 3);
        rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getCarId, cleanListTo.getCarId());
        List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(rptCarWorkQueryWrapper);

        Map<String, TlFacilities> tlFacilitiesMap = tlFacilitiesMapper.selectList(new QueryWrapper<>()).stream().collect(Collectors.groupingBy(TlFacilities::getId, Collectors.collectingAndThen(toList(), facilities -> facilities.get(0))));

        Set<String> countCleanList = new HashSet<>();
        Set<String> cleanList = new HashSet<>();

        for (RptCarWork rptCarWork : rptCarWorkList) {
            String[] sjdIds = rptCarWork.getSjdIds().split(",");
            for (String sjdId : sjdIds) {
                countCleanList.add(sjdId);
            }
            List<RptCarWorkFacility> rptCarWorkFacilityList1 = rptCarWorkFacilityListMap.get(rptCarWork.getId());
            if (null != rptCarWorkFacilityList1) {
                for (RptCarWorkFacility rptCarWorkFacility : rptCarWorkFacilityList1) {
                    String pointId = rptCarWorkFacility.getCollectPointId();
                    Integer cleanType = rptCarWorkFacility.getCleanType();
                    if (null != cleanType && cleanType == 1) {
                        cleanList.add(pointId);
                    } else {
                        System.out.println("error " + pointId);
                    }

                }
            }
        }
        FaclCleanListVo faclCleanListVo = new FaclCleanListVo();
        Set<CleanListVo> cleanListVoList = new HashSet<>();
        //已清
        for (String falcId : cleanList) {
            CleanListVo cleanListVo = new CleanListVo();
            TlFacilities tlFacilities = tlFacilitiesMap.get(falcId);
            if (null != tlFacilities) {
                cleanListVo.setId(tlFacilities.getId());
                cleanListVo.setFaclname(tlFacilities.getFaclname());
                cleanListVo.setIsClean(1);
                String[] split = tlFacilities.getFacladdr().split(",");
                cleanListVo.setLat(split[1]);
                cleanListVo.setLng(split[0]);
                cleanListVo.setFacladdrdetail(tlFacilities.getFacladdrdetail());
                cleanListVoList.add(cleanListVo);
            }
        }
        //未清
        List<NotCleanListVo> notCleanListVoList = new ArrayList<>();
        List<String> reduce = countCleanList.stream().filter(item -> !cleanList.contains(item)).collect(toList());
        System.out.println("---差集 reduce1 (list1 - list2)---");
        reduce.parallelStream().forEach(System.out::println);
        for (String id : reduce) {
            NotCleanListVo notCleanListVo = new NotCleanListVo();
            TlFacilities tlFacilities = tlFacilitiesMap.get(id);
            if (null != tlFacilities) {
                notCleanListVo.setId(tlFacilities.getId());
                notCleanListVo.setFaclname(tlFacilities.getFaclname());
                notCleanListVo.setIsClean(0);
                String[] split = tlFacilities.getFacladdr().split(",");
                notCleanListVo.setLat(split[1]);
                notCleanListVo.setLng(split[0]);
                notCleanListVo.setFacladdrdetail(tlFacilities.getFacladdrdetail());
                notCleanListVoList.add(notCleanListVo);
            }
        }
        faclCleanListVo.setCleanListVoList(cleanListVoList);
        faclCleanListVo.setNotCleanListVoList(notCleanListVoList);
        System.out.println(faclCleanListVo);
        return faclCleanListVo;
    }

    @Override
    public List<StateOilDevice> getStateOilDevices(String carId, Date date) {
        QueryWrapper<StateOilDevice> stateOilDeviceQueryWrapperBeginServenDay = new QueryWrapper<>();
        stateOilDeviceQueryWrapperBeginServenDay.lambda().orderByAsc(StateOilDevice::getDeviceDate);
        Date starttimeBeginServenDay = Tools.getDateForBeginServenDay(date);
        Date endtimeBeginServenDay = Tools.getDateForEnd(date);
        stateOilDeviceQueryWrapperBeginServenDay.lambda().between(StateOilDevice::getDeviceDate, starttimeBeginServenDay, endtimeBeginServenDay);
        stateOilDeviceQueryWrapperBeginServenDay.lambda().gt(StateOilDevice::getUseOilNum, 0);
        if (StringUtils.isNotEmpty(carId)) {
            stateOilDeviceQueryWrapperBeginServenDay.lambda().eq(StateOilDevice::getCarId, carId);
        }
        List<StateOilDevice> stateOilDeviceList = stateOilDeviceMapper.selectList(stateOilDeviceQueryWrapperBeginServenDay);
        return stateOilDeviceList;
    }

    @Override
    public BigDecimal getAlarmOilWearNum(List<StateOilDevice> stateOilDeviceList, BigDecimal factor2) {
        BigDecimal oil = BigDecimal.ZERO;
        BigDecimal distance = BigDecimal.ZERO;
        for (StateOilDevice stateOilDevice : stateOilDeviceList) {
            distance = distance.add(stateOilDevice.getClockMileage());
            oil = oil.add(stateOilDevice.getUseOilNum());
        }
        if (distance.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else {
            return oil.multiply(factor2).divide(distance, 2, BigDecimal.ROUND_HALF_UP);
        }

    }

    @Override
    public List<CarTrack> getCarTracks(String carId, Date date) {
        QueryWrapper<CarTrack> carTrackQueryWrapperBeginServenDay = new QueryWrapper<>();
        carTrackQueryWrapperBeginServenDay.lambda().orderByAsc(CarTrack::getTimestamp);
        carTrackQueryWrapperBeginServenDay.lambda().orderByAsc(CarTrack::getCreateTime);
        Date starttimeBeginServenDay = Tools.getDateForBeginServenDay(date);
        Date endtimeBeginServenDay = Tools.getDateForEnd(date);
        carTrackQueryWrapperBeginServenDay.lambda().between(CarTrack::getTimestamp, starttimeBeginServenDay, endtimeBeginServenDay);
//        carTrackQueryWrapperBeginServenDay.lambda().gt(CarTrack::getOilMass, 0);
        carTrackQueryWrapperBeginServenDay.lambda().select(CarTrack::getCarId, CarTrack::getTimestamp,
                CarTrack::getCreateTime, CarTrack::getOilMass, CarTrack::getAddOilNum, CarTrack::getDistanceBetween,
                CarTrack::getIsOilmassAbnormal, CarTrack::getSpeed, CarTrack::getMoveSecond, CarTrack::getLng, CarTrack::getLat
        );
        carTrackQueryWrapperBeginServenDay.lambda().isNotNull(CarTrack::getCarId);
        if (StringUtils.isNotEmpty(carId)) {
            carTrackQueryWrapperBeginServenDay.lambda().eq(CarTrack::getCarId, carId);
        }
        List<CarTrack> carTrackListBeginServenDay = carTrackMapper.selectList(carTrackQueryWrapperBeginServenDay);
        if (CollectionUtils.isEmpty(carTrackListBeginServenDay)) {
            getCarTracks(carId, Tools.getDateForNextServenDay(date));
        }
        return carTrackListBeginServenDay;
    }

    @Override
    public BigDecimal getAlarmOilWearNum(String carId, List<CarTrack> carTrackListBeginServenDay, BigDecimal factor2) {
        //加油量
        BigDecimal addOilWear = BigDecimal.ZERO;
        //总里程数
        BigDecimal totalMileage = BigDecimal.ZERO;
        BigDecimal startOilMss = BigDecimal.ZERO;
        BigDecimal endOilMss = BigDecimal.ZERO;
        BigDecimal oilWear = BigDecimal.ZERO;
        Map<String, List<CarTrack>> carTrackMap = GroupingByUtils.getGroupingForMapList(carTrackListBeginServenDay, CarTrack::getCarId);
        List<CarTrack> carTrackList = carTrackMap.get(carId);

        if (!carTrackMap.containsKey(carId)) {
            return BigDecimal.ZERO;
        }
        for (int i = 1; i < carTrackList.size(); i++) {
            Double distance = locationUtil.getDistance(carTrackList.get(i).getLat(), carTrackList.get(i).getLng(), carTrackList.get(i - 1).getLat(), carTrackList.get(i - 1).getLng());
            totalMileage = (MathUtils.getBigDecimal(distance).add(totalMileage));
            Double addNumber = null == carTrackList.get(i).getAddOilNum() ? 0D : carTrackList.get(i).getAddOilNum();
            addOilWear = addOilWear.add(MathUtils.getBigDecimal(addNumber));
        }
        if (carTrackList != null && !carTrackList.isEmpty()) {
            startOilMss = carTrackList.get(0).getOilMass();
            endOilMss = carTrackList.get(carTrackList.size() - 1).getOilMass();
        }
        //油耗
        oilWear = MathUtils.getBigDecimal(startOilMss).subtract(MathUtils.getBigDecimal(endOilMss)).add(addOilWear).setScale(2, BigDecimal.ROUND_HALF_UP);

        if (oilWear != null && totalMileage != null && factor2 != null && totalMileage.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal res = oilWear.divide(totalMileage, 6, BigDecimal.ROUND_HALF_UP).multiply(factor2);
            return res;
        } else {
            return BigDecimal.ZERO;
        }
    }

    @Override
    public void updateOilAndTimeConsuming(MileageAndOilWearTo mileageAndOilWearTo) {

        List<Grid> gridList = gridMapper.selectList(new QueryWrapper<>());
        Map<String, Grid> gridMap = gridList.stream().collect(Collectors.groupingBy(Grid::getGridId, Collectors.collectingAndThen(Collectors.toList(), grids -> grids.get(0))));

        QueryWrapper<TlCar> tlCarQueryWrapper = new QueryWrapper<>();
        List<TlCar> tlCarList = tlCarMapper.selectList(tlCarQueryWrapper);

        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        carTrackQueryWrapper.lambda().between(CarTrack::getWorkDay, mileageAndOilWearTo.getStartDate(), mileageAndOilWearTo.getEndDate());
        List<CarTrack> carTrackList1 = carTrackMapper.selectList(carTrackQueryWrapper);
        Map<String, List<CarTrack>> carTrackMap = carTrackList1.stream().collect(Collectors.groupingBy(CarTrack::getCarId));

        QueryWrapper<RptCarWork> carWorkQueryWrapper = new QueryWrapper<>();
        carWorkQueryWrapper.between("work_date", mileageAndOilWearTo.getStartDate(), mileageAndOilWearTo.getEndDate());
        carWorkQueryWrapper.lambda().eq(RptCarWork::getWorkType, 2);
        List<RptCarWork> rptCarWorkList1 = rptCarWorkMapper.selectList(carWorkQueryWrapper);
        Map<String, List<RptCarWork>> rptCarWorkMap = rptCarWorkList1.stream().collect(Collectors.groupingBy(RptCarWork::getCarId));

        for (TlCar tlCar : tlCarList) {
            List<CarTrack> carTrackList = carTrackMap.get(tlCar.getId());
            if (null != carTrackList) {
                for (int i = 1; i < carTrackList.size(); i++) {
//                    QueryWrapper<RptCarWork> carWorkQueryWrapper = new QueryWrapper<>();
//                    carWorkQueryWrapper.eq("car_id", carTrackList.get(i).getCarId());
//                    carWorkQueryWrapper.between("work_date", mileageAndOilWearTo.getStartDate(), mileageAndOilWearTo.getEndDate());
//                    List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(carWorkQueryWrapper);
                    List<RptCarWork> rptCarWorkList = rptCarWorkMap.get(carTrackList.get(i).getCarId());
                    if (null != rptCarWorkList) {
                        BigDecimal nowProgress;
                        BigDecimal timeConsuming;
                        BigDecimal oilConsumption;
                        BigDecimal mileage;
                        for (RptCarWork rptCarWork : rptCarWorkList) {
                            Grid grid = gridMap.get(rptCarWork.getGridId());
                            if (null != grid) {
                                boolean isInGrid = DistanceUtils.insideGrid(Double.parseDouble(carTrackList.get(i).getLng()), Double.parseDouble(carTrackList.get(i).getLat()), gridMap.get(rptCarWork.getGridId()));
                                if (isInGrid) {
                                    if (rptCarWork.getPlanStartTime().compareTo(carTrackList.get(i).getTimestamp()) <= 0 && rptCarWork.getPlanEndTime().compareTo(carTrackList.get(i).getTimestamp()) >= 0) {
                                        //开启喷头总进度   1  //喷头开启 暂时去掉   && currentCarTrack.getStatus() == 1
                                        if (null != carTrackList.get(i).getStatus() && carTrackList.get(i).getStatus() == 1) {

                                            nowProgress = rptCarWork.getWorkMileage().add(new BigDecimal(carTrackList.get(i).getDistanceBetween()));

                                            if (carTrackList.get(i).getTimestamp().compareTo(rptCarWork.getPlanEndTime()) <= 0
                                                    && carTrackList.get(i).getTimestamp().compareTo(rptCarWork.getPlanStartTime()) >= 0) {
                                                rptCarWork.setWorkMileage(nowProgress);
                                            }
                                        }


                                        //作业油耗
                                        if (carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO) > 0) {
                                            BigDecimal addOliNum = null == carTrackList.get(i).getAddOilNum() ? BigDecimal.ZERO : new BigDecimal(carTrackList.get(i).getAddOilNum());
                                            BigDecimal oilMass = carTrackList.get(i - 1).getOilMass();
                                            BigDecimal oilMass1 = carTrackList.get(i).getOilMass();
                                            BigDecimal oilWear = oilMass.subtract(oilMass1).
                                                    add(addOliNum);
                                            if (null != rptCarWork.getWorkOil()) {
                                                oilConsumption = rptCarWork.getWorkOil().add(oilWear);
                                            } else {
                                                oilConsumption = oilWear;
                                            }
                                            if (oilConsumption.compareTo(BigDecimal.ZERO) < 0) {
                                                oilConsumption = BigDecimal.ZERO;
                                            }
                                            rptCarWork.setWorkOil(oilConsumption);
                                        }
                                        mileage = (null == rptCarWork.getWorkMileage() ? BigDecimal.ZERO : rptCarWork.getWorkMileage()).add(new BigDecimal(carTrackList.get(i).getDistanceBetween()));
                                        rptCarWork.setWorkMileage(mileage);
                                        if (null == rptCarWork.getWorkStartTime() || "".equals(rptCarWork.getWorkStartTime())) {
                                            rptCarWork.setWorkStartTime(carTrackList.get(i).getTimestamp());
                                        }
                                        rptCarWork.setWorkEndTime(carTrackList.get(i).getTimestamp());
                                        timeConsuming = new BigDecimal(rptCarWork.getWorkEndTime().getTime() - rptCarWork.getWorkStartTime().getTime()).divide(new BigDecimal(1000));
                                        //作业耗时
//                            timeConsuming = (null == rptCarWork.getTimeConsuming() ? BigDecimal.ZERO : rptCarWork.getTimeConsuming()).add(new BigDecimal((carTrackList.get(i).getTimestamp().getTime() - carTrackList.get(i - 1).getTimestamp().getTime()) / 1000));
                                        rptCarWork.setWorkTime(timeConsuming);

                                        rptCarWorkMapper.updateById(rptCarWork);
                                    }
                                }
                            }
                        }
                    }

                }
            }

        }

    }

    @Override
    public void updateRptCarWorkByWorkType() {
//        QueryWrapper<RptCarWork> rptCarWorkQueryWrapper = new QueryWrapper<>();
//        rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getWorkType, 1);
//        List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(rptCarWorkQueryWrapper);
//
//        List<JxqsPlan> jxqsPlanList = jxqsPlanMapper.selectList(new QueryWrapper<>());
//        List<String> carIdList = new ArrayList<>();
//        for (JxqsPlan jxqsPlan : jxqsPlanList) {
//            String[] split = jxqsPlan.getCarIds().split(",");
//            for (String s : split) {
//                carIdList.add(s);
//            }
//        }
//
//        List<LjqyWorkPlan> ljqyWorkPlanList = ljqyWorkPlanMapper.selectList(new QueryWrapper<>());
//        Map<String, List<LjqyWorkPlan>> ljqyWorkPlanMap = ljqyWorkPlanList.stream().collect(Collectors.groupingBy(LjqyWorkPlan::getWorkCarId));
//
//
//        List<LjzyWorkPlan> ljzyWorkPlanList = ljzyWorkPlanMapper.selectList(new QueryWrapper<>());
//        Map<String, List<LjzyWorkPlan>> ljzyWorkPlanMap = ljzyWorkPlanList.stream().collect(Collectors.groupingBy(LjzyWorkPlan::getCarId));
//
//
//        for (RptCarWork rptCarWork : rptCarWorkList) {
//            if (carIdList.contains(rptCarWork.getCarId())) {
//                rptCarWork.setWorkType(2);
//            }
//            if (null != ljqyWorkPlanMap.get(rptCarWork.getCarId())) {
//                rptCarWork.setWorkType(3);
//            }
//            if (null != ljzyWorkPlanMap.get(rptCarWork.getCarId())) {
//                rptCarWork.setWorkType(4);
//            }
//            rptCarWorkMapper.updateById(rptCarWork);
//        }
    }

    @Override
    public void processingStopPointCarTrack(OilNumTO oilNumTO) {
        List<Date> dateList = Tools.getBetweenDateList(oilNumTO.getStartTime(), oilNumTO.getEndTime());
        SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
        List<TlCar> carList = carService.list();
        List<CarTrack> deleteList = new ArrayList<>();
        for (Date date : dateList) {
            for (TlCar car : carList) {
                List<CarTrack> carTrackOriginalList = carTrackMapper.selectList(new QueryWrapper<CarTrack>().lambda()
                        .between(CarTrack::getTimestamp, Tools.getDateForBegin(date),
                                Tools.getDateForEnd(date))
                        .eq(CarTrack::getCarId, car.getId()).orderByAsc(CarTrack::getTimestamp));
                deleteList.addAll(processingStopPointCarTrack(carTrackOriginalList));
            }
            log.info(sp.format(date) + "--processingStopPointCarTrackprocessingStopPointCarTrackprocessingStopPointCarTrack");
        }
        List<String> ids = deleteList.stream().map(CarTrack::getId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ids)) {
            carTrackMapper.deleteBatchIds(ids);
        }

    }

    private List<CarTrack> processingStopPointCarTrack(List<CarTrack> carTrackOriginalList) {
        List<CarTrack> result = new ArrayList<>();
        for (int i = 1; i < carTrackOriginalList.size(); i++) {
            CarTrack thisTrack = carTrackOriginalList.get(i);
            CarTrack lastTrack = carTrackOriginalList.get(i - 1);
            Long thisTrackTimeNum = thisTrack.getTimestamp().getTime();
            Long lastTrackTimeNum = lastTrack.getTimestamp().getTime();
            Long TrackTimeNumDad = thisTrackTimeNum - lastTrackTimeNum;
            double differenceMeter = locationUtil.getDistance(lastTrack.getLat(), lastTrack.getLng(), thisTrack.getLat(), thisTrack.getLng());
            if (locationUtil.realOffLine(differenceMeter, TrackTimeNumDad)) {
                result.add(thisTrack);
            }

        }
        return result;
    }

    @Override
    public void supplementaryCarTrackPoints(OilNumTO oilNumTO) {
        QueryWrapper<CarTrack> trackQueryWrapper = new QueryWrapper<>();
        trackQueryWrapper.lambda().between(CarTrack::getTimestamp, oilNumTO.getStartTime(), oilNumTO.getEndTime());
        List<CarTrack> carTrackList = list(trackQueryWrapper);
        if (CollectionUtils.isNotEmpty(carTrackList)) {
            removeByIds(carTrackList.stream().map(CarTrack::getId).collect(toList()));
        }
        List<CarTrack> insertList = new ArrayList<>();
        Map<String, TlCar> carMap = carService.getCarMap(new QueryWrapper<>());
        List<KfkCarLocation> kfkCarLocationList = kfkCarLocationService.list(new QueryWrapper<KfkCarLocation>().lambda()
                .between(KfkCarLocation::getTimestamp, oilNumTO.getStartTime(), oilNumTO.getEndTime())
                .orderByAsc(KfkCarLocation::getTimestamp));
        insertList.addAll(supplementaryCarTrackPoints(kfkCarLocationList));
        insertList.forEach(x -> x.setOilMass(x.getOilMass().multiply(StringUtils.isNotEmpty(
                carMap.get(x.getCarId()).getTankvolcheck()) ? new BigDecimal(
                carMap.get(x.getCarId()).getTankvolcheck()) : BigDecimal.ZERO).divide(new BigDecimal(100), BigDecimal.ROUND_HALF_UP)));
        if (CollectionUtils.isNotEmpty(insertList)) {
            saveBatch(insertList);
        }

    }

    private List<CarTrack> supplementaryCarTrackPoints(List<KfkCarLocation> kfkCarLocationList) {
        List<CarTrack> result = new ArrayList<>();
        for (KfkCarLocation kfkCarLocation : kfkCarLocationList) {
            result.add(buildCarTrack(kfkCarLocation));
        }
        return result;
    }


    private CarTrack buildCarTrack(KfkCarLocation kfkCarLocation) {
        CarTrack currentCarTrack = new CarTrack();
        currentCarTrack.setId(IdUtils.simpleUUID());
        currentCarTrack.setCarId(kfkCarLocation.getCarid());
        currentCarTrack.setEqpNum(kfkCarLocation.getEqpnum());
        currentCarTrack.setOilMass(BigDecimal.valueOf(kfkCarLocation.getOilmass()));
        currentCarTrack.setMessage(String.valueOf(kfkCarLocation.getMileage()));
        currentCarTrack.setWorkMonth(StringUtils.dateToStr(kfkCarLocation.getTimestamp(), "yyyy-MM"));
        currentCarTrack.setWorkDay(kfkCarLocation.getTimestamp());
        currentCarTrack.setLng(kfkCarLocation.getLon());
        currentCarTrack.setLat(kfkCarLocation.getLat());
        currentCarTrack.setLocation(kfkCarLocation.getLon() + "," + kfkCarLocation.getLat());
        currentCarTrack.setAddress(locationUtil.getAddress(kfkCarLocation.getLon(), kfkCarLocation.getLat()));
        currentCarTrack.setSpeed(kfkCarLocation.getSpeed());
        currentCarTrack.setMessage("");
        currentCarTrack.setIsDanger(0);
        currentCarTrack.setIsWarning(0);
        currentCarTrack.setTimestamp(kfkCarLocation.getTimestamp());
        currentCarTrack.setStatus(Integer.parseInt(kfkCarLocation.getStatus()));
        currentCarTrack.setCreateTime(new Date());
        currentCarTrack.setDangerOil(0.0);
        currentCarTrack.setDangerOverSpeed(0);
        currentCarTrack.setWarningOverSpeed(0);
        currentCarTrack.setWarningDriveEmpty(0);
        currentCarTrack.setWarningLowSpeed(0);
        currentCarTrack.setWarningStay(0);
        currentCarTrack.setWarningLeave(0);
        currentCarTrack.setWarningOil(0);
        currentCarTrack.setMoveSecond(0);
        currentCarTrack.setMileage(kfkCarLocation.getMileage());
        currentCarTrack.setIsInGrid(0);
        currentCarTrack.setDirection(kfkCarLocation.getDirection());
        return currentCarTrack;
    }

}
